/*
 * Copyright (c) 2024, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "i2c_target.h"

/*====================== FORWARD DECLARATIONS ==============================*/

/*============================ TYPEDEFS ====================================*/
typedef uint32_t tMask;

/*============================ EXTERNS =====================================*/
extern uint8_t TxBuffer[];
extern uint8_t RxBuffer[];

/*====================== DEFINES/MACROS ====================================*/
#define IOX_NUM_OF_PORTS                        (2)

/*============================ VARIABLES ===================================*/
/*
 * PORT MASK configuration
 * Set the NUM_OF_PORTS below according to the target device.
 *
 * To define which pins will be active on the IO expander, set the
 * corresponding PORTx as follows:
 *
 * Setting bit =  '1' indicates the pin is active and can be modified by the host MCU.
 * Setting bit =  '0' indicates the pin is not used.
 *
 *  PROTOCOL
 *  [BYTE 0]: 0 = PORTA, 1 = PORTB, 2 = PORTC
 *  [BYTE 1]: 0 = DIN, 1 = DOUT, 2 = CLEAR, 3 = SET, 4 = TOGGLE
 *  [BYTE 2][BYTE 3][BYTE 4][BYTE 5] = 32-BIT data
 */

/*
 * The GPIO defines represent the MSPM0L/G LaunchPad pins used in this example.
 * See the peripheralPinAssignments.txt file generated by Sysconfig.
 *
 * Be sure that the mask matches the physical pins used on the io expander.
 *
- GPIOA:
    + High-Speed Input with internal pull-down: PA13
    + Standard with Wake Input: PA18
    + Open-Drain Output: PA0
- GPIOB:
    + Standard Output: PB26
    + Standard Output: PB27
    + Standard Output: PB22
    + Standard Input with internal pull-up: PB21
    + Standard Output with internal pull-up: PB0
    + Standard Output: PB4
 */
/*
#define USER_IN                                 (DL_GPIO_PIN_13)    // 0x00002000
#define SW_S2 (BSL)                             (DL_GPIO_PIN_18)    // 0x00004000
#define SW_S3 (USER)                            (DL_GPIO_PIN_21)    // 0x00000400
#define LED_RGB_GREEN                           (DL_GPIO_PIN_27)    // 0x08000000
#define LED_RGB_RED                             (DL_GPIO_PIN_26)    // 0x04000000
#define LED_RGB_BLUE                            (DL_GPIO_PIN_22)    // 0x00400000
#define IRQ_OUT                                 (DL_GPIO_PIN_0)     // 0x00000001
*/


/*============================ VARIABLES ===================================*/
tPacket Packet;

//=================================================
// User modifies this section, PORT A:
// Configure InputMask and Output masks for PORTA.
//=================================================
#define PORTA_inputMask (GPIO_A_USER_IN_PIN | GPIO_A_SW_S2_PIN )

#define PORTA_outputMask (0x00000000)

#if (IOX_NUM_OF_PORTS == 1)
GPIO_Regs* portList[] = {(GPIO_Regs*)GPIOA_BASE};
const tMask inputMasks[] = {PORTA_inputMask};
const tMask outputMasks[] = {PORTA_outputMask};
#endif


//=================================================
// If device has PORT B:
// User modifies this section.
// Configure InputMask and Output masks for PORTB.
//=================================================
#if (IOX_NUM_OF_PORTS > 1)
#define PORTB_inputMask (GPIO_B_SW_S3_PIN)

#define PORTB_outputMask (GPIO_B_LED_RED_PIN | \
                                GPIO_B_LED_GREEN_PIN | \
                                GPIO_B_LED_BLUE_PIN | \
                                GPIO_B_IRQ_OUT_PIN | \
                                GPIO_B_USER_OUT_PIN)
#endif
#if (IOX_NUM_OF_PORTS == 2)
GPIO_Regs* portList[] = {(GPIO_Regs*)GPIOA_BASE, (GPIO_Regs*)GPIOB_BASE};
const tMask inputMasks[] = {PORTA_inputMask, PORTB_inputMask};
const tMask outputMasks[] = {PORTA_outputMask, PORTB_outputMask};
#endif

//=================================================
// If device has PORT C:
// User modifies this section.
// Configure InputMask and Output masks for PORTC.
//=================================================
#if (IOX_NUM_OF_PORTS > 2)
#define PORTC_inputMask (0x00000000)
#define PORTC_outputMask (0x00000000)
#endif

#if (IOX_NUM_OF_PORTS == 3)
GPIO_Regs* portList[] = {(GPIO_Regs*)GPIOA_BASE, (GPIO_Regs*)GPIOB_BASE, (GPIO_Regs*)GPIOC_BASE};
const tMask inputMasks[] = {PORTA_inputMask, PORTB_inputMask, PORTC_inputMask};
const tMask outputMasks[] = {PORTA_outputMask, PORTB_outputMask, PORTC_outputMask};
#endif
/*============================ FUNCTIONS ===================================*/

/*
 * Simple message processor
 */
void processMessage(void)
{
    GPIO_Regs* GPIO_Port;
    uint32_t ui32Data;

    /* Extract packet info and populate port object */
    deSerializePacket(&Packet, RxBuffer);

    /* Look up actual PORT address for this device */
    GPIO_Port = portList[Packet.PortNum];

    /* Use output mask to allow only specified bits to be modified */
    ui32Data = (Packet.Data.ui32Full & (tMask)outputMasks[Packet.PortNum]);

    /*======== Perform action on selected port register ==========*/
    switch(Packet.Register)
    {
    case eDIN:

        /* Read the requested GPIO.
         * Use input mask to allow only specified bits to be modified
         */
        Packet.Data.ui32Full =  DL_GPIO_readPins(GPIO_Port, (tMask)inputMasks[Packet.PortNum]);

        /* Serialize the object...populate Tx_Buffer */
        serializePacket(&Packet, TxBuffer);

        /*
         * Enabling TXFIFO interrupt will automatically load the TXFIFO register with the packet
         */
        DL_I2C_enableInterrupt(I2C_TARGET_INST, DL_I2C_INTERRUPT_TARGET_TXFIFO_TRIGGER);
        break;
        
    case eDOUT: /* Update all pins at same time*/
        DL_GPIO_writePins(GPIO_Port, ui32Data);
        break;
        
    case eDOUT_CLEAR: /* Clear only selected pins */
        DL_GPIO_clearPins(GPIO_Port, ui32Data);
        break;
        
    case eDOUT_SET: /* Set only selected pins */
        DL_GPIO_setPins(GPIO_Port, ui32Data);
        break;
        
    case eDOUT_TOGGLE: /* Toggle only selected pins */
        DL_GPIO_togglePins(GPIO_Port, ui32Data);
        break;
        
     }// end switch
}



